#include "CClient.h"


//////////////////////////////////////////////////////////////////
//  CBuff
//////////////////////////////////////////////////////////////////

CBuff::CBuff(IN UINT size)
{
    m_pBuff = new char[size];
    m_nEndPos = 0;
    m_nSize = size;
}

CBuff::~CBuff()
{
    if (m_pBuff)
    {
        delete[] m_pBuff;
        m_pBuff = nullptr;
    }
}

BOOL CBuff::Append(IN const char* data, IN const UINT length)
{
    BOOL bRet = FALSE;

    if (m_nSize - m_nEndPos >= length)
    {
        memcpy(m_pBuff + m_nEndPos, data, length);
        m_nEndPos += length;
        bRet = TRUE;
    }

    return bRet;
}


//////////////////////////////////////////////////////////////////
//  CSendBuff
//////////////////////////////////////////////////////////////////

CSendBuff::CSendBuff(IN UINT size) : CBuff(size)
{
}

CSendBuff::~CSendBuff()
{
}

int CSendBuff::Send(IN SOCKET socket)
{
    if (!GetEndPos()) return 0;

    int nRetLen = send(socket, GetBuff(), GetEndPos(), 0);
    ResetEndPos();
    return nRetLen;
}


//////////////////////////////////////////////////////////////////
//  CRecvBuff
//////////////////////////////////////////////////////////////////

CRecvBuff::CRecvBuff(IN UINT size) : CBuff(size)
{
}

CRecvBuff::~CRecvBuff()
{
}

int CRecvBuff::Recv(IN SOCKET socket)
{
    int nLen = 0;

    nLen = recv(socket, GetBuff() + GetEndPos(), GetBuffSize() - GetEndPos(), 0);
    if (nLen > 0)
        AdvanceEndPos(nLen);

    return nLen;
}


//////////////////////////////////////////////////////////////////
//  CSocket
//////////////////////////////////////////////////////////////////

int CSocket::SendAsyn(IN NET_PACKET_HEADER* pHeader)
{
    if (!pHeader) return 0;

    int nRetLen = 0;
    int nLen = pHeader->nDataLength;
    char* pSendData = (char*)pHeader;

    if (m_SendBuff.Append(pSendData, nLen))
        nRetLen = nLen;

    return nRetLen;
}

BOOL CSocket::isFullMsg()
{
    if (m_RecvBuff.GetEndPos() >= sizeof(NET_PACKET_HEADER))
    {
        NET_PACKET_HEADER* Header = (NET_PACKET_HEADER*)m_RecvBuff.GetBuff();
        return (m_RecvBuff.GetEndPos() >= (UINT)(Header->nDataLength));
    }
    return FALSE;
}

BOOL CSocket::RemoveHeadMsg()
{
    if (!isFullMsg()) return FALSE;

    NET_PACKET_HEADER* Packet = (NET_PACKET_HEADER*)(m_RecvBuff.GetBuff());
    UINT nStartPos = (UINT)(Packet->nDataLength);
    UINT nRestLen = m_RecvBuff.GetEndPos() - nStartPos;

    memcpy(m_RecvBuff.GetBuff(), m_RecvBuff.GetBuff() + nStartPos, nRestLen);
    m_RecvBuff.RetreatEndPos(nStartPos);

    return TRUE;
}


//////////////////////////////////////////////////////////////////
//  CSelClient
//////////////////////////////////////////////////////////////////

CSelClient::CSelClient()
{
}

CSelClient::~CSelClient()
{
}

BOOL CSelClient::RunClient()
{
    if (!isConnect()) return FALSE;

    fd_set fdsRead = { 0 };
    timeval tv = { 1, 0 };

    FD_ZERO(&fdsRead);
    FD_SET(GetSocket(), &fdsRead);

    select((int)GetSocket() + 1, &fdsRead, NULL, NULL, &tv);

    if (FD_ISSET(GetSocket(), &fdsRead))
    {
        FD_CLR(GetSocket(), &fdsRead);

        if (SOCKET_HANDLE != OnHandleMsg())
        {
            Close();
            return FALSE;
        }
    }

    return TRUE;
}


//////////////////////////////////////////////////////////////////
//  CClient
//////////////////////////////////////////////////////////////////

SOCKET_STATUS CClient::MsgProc(IN NET_PACKET_HEADER* lpHeader)
{
    static size_t i = 0;
    NET_COMMON_PACKET packet;

    switch (lpHeader->nCmd)
    {
    case NORMALACK:
        //printf("%lld-%s\r\n", ++i, ((NET_COMMON_PACKET*)lpHeader)->strInfo);
        //printf("<socket>%lld</socket>\t<Length>%d</Length\t><id>%lld</id>\r\n", ClientSocket, lpHeader->nDataLength, i++);
        //send(GetSocket(), (const char*)&packet, sizeof(NET_COMMON_PACKET), 0);
        strcpy(packet.strInfo, "Windows 11");
        Send(&packet);
        break;
    case LOGIN:
        break;
    case USERON:
        //printf("<socket>%lld</socket>\t<Length>%d</Length>\t<id>%lld</id>\r\n", ClientSocket, lpHeader->nDataLength, i++);
        break;
    case USEROFF:
        //printf("<socket>%lld</socket>\t<Length>%d</Length>\t<id>%lld</id>\r\n", ClientSocket, lpHeader->nDataLength, i++);
        break;
    case DISCONNECT:
        return SOCKET_CLOSE;
        break;
    default:
        printf("Error\r\n");
        break;
    }

    return SOCKET_HANDLE;
}
